package com.h2cloud.aspect.ThreadLockCache;

import com.h2cloud.aspect.BaseAspect;
import com.h2cloud.depends.cache.ThreadLocalCacheManager;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/***
 * 本地线程缓存拦截器
 */
//@Order(5)
//@Aspect
//@Component
public class ThreadLocalCacheAspect extends BaseAspect {

    private final static Logger logger = LoggerFactory.getLogger(ThreadLocalCacheAspect.class);

    /**
     * 后期改成配置
     */
    private static boolean isCacheEnabled = true;

    @Pointcut("@annotation(com.h2cloud.aspect.ThreadLockCache.ThreadLocalCacheable)")
    public void methodPointCut() {

    }

    /**
     *
     */
    @Around("methodPointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {

        ThreadLocalCacheable cacheable;
        //开启缓存
        if (isCacheEnabled && (cacheable = getAnnotation(joinPoint, ThreadLocalCacheable.class)) != null) {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = getArgStr(joinPoint.getArgs(), cacheable.paramName(), joinPoint.getSignature());

            String key = getCacheKey(cacheable.key(), targetName, methodName, arguments);
            logger.debug("aop start,,local cacheKey:{}", key);
            Map<String, Object> cache = ThreadLocalCacheManager.getCache();
            if (cache == null) {
                cache = new HashMap<>();
            } else if (cache.containsKey(key)) {
                logger.info("aop end,get result from cache, cacheKey={}", key);
                return cache.get(key);
            }
            Object result = joinPoint.proceed();
            cache.put(key, result);
            ThreadLocalCacheManager.setCache(cache);
            logger.info("aop end,get result from DB, cacheKey={}", key);
            return result;
        } else {
            logger.info("aop end,get result from DB, cache.enabled=false");
            return joinPoint.proceed();
        }
    }
}
